package com.hwtx.form;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class JsonHierarchyFinder {

    private static class SearchResult {
        JsonNode target;
        List<JsonNode> ancestors;

        SearchResult(JsonNode target, List<JsonNode> ancestors) {
            this.target = target;
            this.ancestors = ancestors;
        }
    }

    /**
     * 查找符合条件的节点及其祖先
     *
     * @param root           根节点
     * @param targetNodeName 目标节点名称（必填）
     * @param targetField    目标节点字段名（可选）
     * @param targetValues   目标节点字段值集合（可选）
     * @param ancestorField  祖先节点字段名（可选）
     * @param ancestorValues 祖先节点字段值集合（可选）
     * @return 包含目标节点和符合条件祖先的列表
     */
    public static List<SearchResult> findNodesWithAncestors(
            JsonNode root,
            String targetNodeName,
            String targetField,
            List<String> targetValues,
            String ancestorField,
            List<String> ancestorValues) {

        List<SearchResult> results = new ArrayList<>();
        traverse(root, new ArrayList<>(), targetNodeName, targetField, targetValues,
                ancestorField, ancestorValues, results);
        return results;
    }

    private static void traverse(
            JsonNode node,
            List<JsonNode> path,
            String targetName,
            String targetField,
            List<String> targetValues,
            String ancestorField,
            List<String> ancestorValues,
            List<SearchResult> results) {

        path.add(node);

        // 检查当前节点是否为目标节点
        if (isTargetNode(node, targetName, targetField, targetValues)) {
            List<JsonNode> validAncestors = filterAncestors(
                    path.subList(0, path.size() - 1), // 排除当前节点
                    ancestorField,
                    ancestorValues
            );
            results.add(new SearchResult(node, validAncestors));
        }

        // 递归处理子节点
        if (node.isObject()) {
            node.fields().forEachRemaining(entry -> {
                List<JsonNode> newPath = new ArrayList<>(path);
                traverse(entry.getValue(), newPath, targetName, targetField, targetValues,
                        ancestorField, ancestorValues, results);
            });
        } else if (node.isArray()) {
            node.forEach(element -> {
                List<JsonNode> newPath = new ArrayList<>(path);
                traverse(element, newPath, targetName, targetField, targetValues,
                        ancestorField, ancestorValues, results);
            });
        }
    }

    // 目标节点验证
    private static boolean isTargetNode(JsonNode node,
                                        String nodeName,
                                        String field,
                                        List<String> values) {
        if (!node.isObject()) return false;
        if (!node.has(nodeName)) return false;

        JsonNode target = node.get(nodeName);

        // 无字段要求时直接返回true
        if (field == null) return true;

        // 有字段要求时验证字段值
        JsonNode valueNode = target.get(field);
        if (valueNode == null) return false;

        String actualValue = valueNode.asText();
        return values == null || values.isEmpty() || values.contains(actualValue);
    }

    // 祖先过滤
    private static List<JsonNode> filterAncestors(List<JsonNode> ancestors,
                                                  String field,
                                                  List<String> values) {
        List<JsonNode> filtered = new ArrayList<>();
        for (JsonNode ancestor : ancestors) {
            if (checkAncestor(ancestor, field, values)) {
                filtered.add(ancestor);
            }
        }
        return filtered;
    }

    // 祖先验证
    private static boolean checkAncestor(JsonNode node,
                                         String field,
                                         List<String> values) {
        if (field == null) return true; // 无字段要求

        if (!node.isObject()) return false;
        JsonNode valueNode = node.get(field);
        if (valueNode == null) return false;

        String actualValue = valueNode.asText();
        return values == null || values.isEmpty() || values.contains(actualValue);
    }

    public static void main(String[] args) throws Exception {
        JsonNode root = getJsonNode();

        // 示例查询：查找所有employee节点，其role为developer，且祖先包含id字段
        List<SearchResult> results = findNodesWithAncestors(
                root,
                "schemaApi",    // 目标节点名称
                null,        // 目标字段
                null, // 目标值
                "type",          // 祖先字段
                List.of("button")           // 不限祖先值
        );
        String json = """
                {
                  "organization": {
                    "id": "org1",
                    "departments": [
                      {
                        "department": {
                          "id": "dept1",
                          "employees": [
                            {
                              "employee": {
                                "id": "emp1",
                                "role": "developer"
                              }
                            }
                          ]
                        }
                      }
                    ]
                  }
                }""";

        results.forEach(result -> {
            System.out.println("\n目标节点: " + result.target);
            System.out.println("符合条件的祖先:");
            result.ancestors.forEach(anc ->
                    System.out.println(" - " + anc.get("id") + " (" + anc + ")"));
        });
    }

    private static JsonNode getJsonNode() throws IOException {
        File file = new File("/Users/warning5/pro/spring-lowcode/boot/src/main/resources/page/sys/user_9.json");
        String jsonString = FileUtils.readFileToString(file, "UTF-8");

        ObjectMapper mapper = new ObjectMapper();
        return mapper.readTree(jsonString);
    }
}